package cn.hloger.spider.demo.authDemo.utils;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 签名
 */
public class SignUtils {
    private static final Logger log = LoggerFactory.getLogger(SignUtils.class);

    /**
     * 增加认证机制的方法
     */
    public static String toSign(Object obj, String requestId, String timestamp) {
        String content = "";
        if (obj instanceof String) {
            content = (String) obj;
        } else {
            if (obj != null) {
                content = JSONObject.toJSONString(obj);
            }
        }
        //校验
        String plain = content + requestId + timestamp;
        return SHA256Util.getSHA256(plain);
    }

    public static boolean isValidRequest(String sign, Object body, String requestId
            , String timestamp, String requestMethod) {
        if ("POST".equals(requestMethod)) {
            return isValidPostRequest(sign, body, requestId, timestamp);
        }
        if ("GET".equals(requestMethod)) {
            return isValidGetRequest(sign, (String) body, requestId, timestamp);
        }
        // todo 其他请求：PUT DELETE
//        return isValidPostRequest(sign, body, devId, devKey, pushTime);
        return true;
    }

    /**
     * POST 请求校验
     *
     * @param sign      签名
     * @param body      body
     * @param devId
     * @param devKey
     * @param timestamp
     * @return
     */
    public static boolean isValidPostRequest(String sign, Object body, String requestId, String timestamp) {
        return isValidSign(sign, body, requestId, timestamp);
    }

    /**
     * POST 请求校验
     *
     * @param sign      签名
     * @param url       url
     * @param requestId
     * @param timestamp
     * @return
     */
    public static boolean isValidGetRequest(String sign, String url, String requestId, String timestamp) {
        //fixme  url是否需要解码
        String content = "";
        try {
            url = URLDecoder.decode(url, "UTF-8");
            content = getUrlParams(url);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("签名认证失败：sign={},url={}", sign, url);
        }
        return isValidSign(sign, content, requestId, timestamp);
    }

    /**
     * 校验
     *
     * @param sign      签名
     * @param content   内容
     * @param devId     开发者id
     * @param devKey    开发者key
     * @param timestamp 调用时间戳  秒级别。 System.currentTimeMillis()/1000
     * @return
     */
    private static boolean isValidSign(String sign, Object content, String requestId, String timestamp) {
        long l = (System.currentTimeMillis() - Long.valueOf(timestamp)) / 1000;
        //校验时间有效性
        if (l >= 3600) {
            throw new RuntimeException("请求时间超过规定范围时间");
        }
        //1.鉴权
        String sysSign = toSign(content, requestId, timestamp);
        return sysSign.equals(sign);
    }
    /**
     * GET请求
     * 对url的参数进行加密
     * 例如：url = xxx?a=1&b=2  =>拿a=1&b=2&出来
     *
     * @param url
     * @param devId
     * @param devKey
     * @return
     */
//    public static String toSignUrl(String url, String devId, String devKey) {
//        String content = "";
//        try {
//            content = getUrlParams(url);
//        } catch (Exception e) {
//        }
//        return toSign(content, devId, devKey);
//    }

    /**
     * 将url参数转换成map
     *
     * @param url www.baidu.com?aa=11&bb=22&cc=33
     * @return
     */
    private static String getUrlParams(String url) throws Exception {
        StringBuffer queryString = new StringBuffer();
        url = url.replace("?", ";");
        if (!url.contains(";")) {
            return url;
        }
        if (url.split(";").length > 0) {
            String[] arr = url.split(";")[1].split("&");
            for (int i = 0; i < arr.length; i++) {
                String[] values = arr[i].split("=");
                String key = values[0];
                String value = values[1];
                queryString.append(key + "=");
                queryString.append(URLEncoder.encode(value, "UTF-8"));
                if (i != (arr.length - 1)) {
                    queryString.append("&");
                }
            }
        }
        return queryString.toString();
    }

    /**
     * 推送时间 秒级别
     *
     * @return
     */
    public static Integer getPushTime() {
        Long now = (System.currentTimeMillis() / 1000);
        return now.intValue();
    }

    public static Integer getTime(Long time) {
        Long now = (time / 1000);
        return now.intValue();
    }

    public static void main(String[] args) throws Exception {
        Map jsonObject = new HashMap();
        jsonObject.put("name", "测试");
        jsonObject.put("phone", "444111");
        jsonObject.put("isAreaAdmin", "测试");
//        List<String> list = new ArrayList<String>();
//        list.add("123");
//        list.add("123");
//        list.add("123");
//        list.add("123");
//        String sign = SignUtils.toSign(new Gson().toJson(list)
//                , "appid"
//                , "123456");
//        System.out.println(sign);
//        String body = new Gson().toJson(new String[]{"123", "123", "123"});
//        String sign2 = SignUtils.toSign(body
//                , "appid"
//                , "123456");
//        System.out.println(body);
//        System.out.println(sign2);
//        String bodyMap = new Gson().toJson(jsonObject);
//        String signbodyMap = SignUtils.toSign(bodyMap
//                , "appid"
//                , "123456");
//        System.out.println(bodyMap);
//        System.out.println(signbodyMap);
    }
//    public static Map<String, String> getGetHeader(String url, String appId, String appKey) {
//        String signUrl = SignUtils.toSignUrl(url, appId, appKey);
//        return getHeader(signUrl, appId);
//    }

    /**
     * @param
     * @return
     */
//    public static Map<String, String> getPostHeader(Object content, String appId, String appKey) {
//        String sign = SignUtils.toSign(content, appId, appKey);
//        return getHeader(sign, appId);
//    }
    private static Map<String, String> getHeader(String sign, String appId) {
        Map<String, String> header = new HashMap<String, String>();
        header.put("timestamp", System.currentTimeMillis() / 1000 + "");
        header.put("devId", appId);
        header.put("sign", sign);
        return header;
    }
}

